﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Asion.Dapper
{
    public static class AssemblyHelper
    {

        /// <summary>
        /// 获取类型通过当前文件目录
        /// </summary>
        /// <param name="type"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public static IList<Type> GetTypeByDirectory(Type type, string name = "")
        {
            var result = new List<Type>();
            var directoryPath = AppDomain.CurrentDomain.BaseDirectory;
            //string directoryPath = "."; // 当前目录
            string searchPattern = "*.dll"; // 搜索模式

            foreach (string file in Directory.GetFiles(directoryPath, searchPattern))
            {
                try
                {
                    Assembly assembly = Assembly.LoadFrom(file);
                    Type[] types = assembly.GetTypes().Where(t => !t.IsInterface && t.FullName.Contains(name) && t.GetInterfaces().Contains(type)).ToArray();
                    result.AddRange(types);
                    /*                    foreach (Type type in types)
                                        {
                                            //if (type.GetInterface(typeof(IScanable).FullName) != null)
                                            //{
                                            //Console.WriteLine($"找到实现IScanable接口的类型: {type.FullName}");
                                            //}
                                            var types = assembly.GetTypes()

                                                   .ToList();
                                            result.AddRange(types);
                                        }*/
                }
                catch (Exception ex)
                {
                    //Console.WriteLine($"无法加载DLL: {file}, 错误: {ex.Message}");
                }
            }
            return result;
        }

        /// <summary>
        /// 获取继承了接口的类型
        /// </summary>
        public static IList<Type> GetInterfaceTypeByExecuting(Type type)
        {
            // 获取当前程序集
            Assembly assembly = Assembly.GetExecutingAssembly();

            // 获取实现了接口的所有类型
            var types = assembly.GetTypes()
                .Where(t => !t.IsInterface && t.GetInterfaces().Contains(type))
                .ToList();

            return types;
        }


        /// <summary>
        /// 获取继承了接口的类型
        /// </summary>
        public static IList<Type> GetInterfaceTypes(Type type)
        {
            var result = new List<Type>();
            //get current quote assemblies
            var assemblies = AppDomain.CurrentDomain.GetAssemblies();

            foreach (var assembly in assemblies)
            {
                var types = assembly.GetTypes()
                                .Where(t => !t.IsInterface && t.GetInterfaces().Contains(type))
                                .ToList();
                result.AddRange(types);
            }
            // 获取实现了接口的所有类型
            return result;
        }


        /// <summary>
        /// 获取为null的列
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static IList<string> GetNullColumns<TEntity>(TEntity type)
        {
            var result = new List<string>();
            var properties = type.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
            foreach (var propertyInfo in properties)
            {
                object value = propertyInfo.GetValue(type, null);
                if (value is null)
                {
                    result.Add(propertyInfo.Name);

                }
                //value is null  if type is time and value <=1970-1-1   
                if (propertyInfo.PropertyType == typeof(DateTime) || propertyInfo.PropertyType == typeof(Nullable<DateTime>))
                {
                    if (value == null)
                    {
                        result.Add(propertyInfo.Name);
                    }
                    else
                    {
                        DateTime.TryParse(value.ToString(), out DateTime date);
                        var minData = new DateTime(1970, 1, 1, 0, 0, 0, 0);
                        if (date <= minData)
                        {
                            result.Add(propertyInfo.Name);
                        }
                    }
                }
            }
            return result;
        }
    }
}
